#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <linux/ethtool.h>
#include <linux/mdio.h>
#include <linux/sockios.h>

#include "mii_led.h"

#define WAN_OP_PATH "/sys/class/leds/25WAN/brightness"
#define LAN_OP_PATH "/sys/class/leds/25LAN/brightness"
#define BRIGHTNESS 		"1"
#define NOBRIGHTNESS	"0"
#define MAKE_BRIGHTNESS(fd) write(fd, BRIGHTNESS, strlen(BRIGHTNESS))
#define MAKE_NOBRIGHTNESS(fd) write(fd, NOBRIGHTNESS, strlen(NOBRIGHTNESS))

int last_wan_status = 0;
int last_lan_status = 0;
unsigned int lan_phy_id = 0, wan_phy_id = 0;
int wan_fd = 0, lan_fd = 0;
int socket_id = -1;

static int wan_lan_fd_init()
{
	if((wan_fd = open(WAN_OP_PATH, O_RDWR)) == -1)
		return -1;
	if((lan_fd = open(LAN_OP_PATH, O_RDWR)) == -1)
		return -1;
}

static void fill_mii_ioctl(struct mii_ioctl_data *mii, uint16_t phy_id,
			   uint16_t reg_num, uint16_t *val)
{
	mii->phy_id  = phy_id;
	mii->reg_num = reg_num;
	mii->val_in  = *val;
	mii->val_out = 0;
}


static void fill_mtk_mii_ioctl(struct mtk_mii_ioctl_data *mtk_mii, uint16_t phy_id,
			      uint16_t reg_num, unsigned int *val)
{
	mtk_mii->phy_id  = phy_id;
	mtk_mii->reg_num = reg_num;
	mtk_mii->val_in  = *val;
	mtk_mii->val_out = 0;
}

static int __phy_op_init()
{
	socket_id = socket(AF_INET, SOCK_DGRAM, 0);
    if (socket_id < 0)
        return -1;
	else
		return socket_id;
}

static int __phy_op(char *ifname, uint16_t phy_id, uint16_t reg_num, unsigned int *val, uint16_t cmd, int is_priv)
{        

        struct ifreq ifr;
        struct mii_ioctl_data mii;
		struct mtk_mii_ioctl_data mtk_mii;
        int err;        

	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';

	if (is_priv) {
		fill_mtk_mii_ioctl(&mtk_mii, phy_id, reg_num, val);
		ifr.ifr_data = (char *)&mtk_mii;
	} else {
		fill_mii_ioctl(&mii, phy_id, reg_num, (uint16_t *)val);
		ifr.ifr_data = (char *)&mii;
	}

        err = ioctl(socket_id, cmd, &ifr);
        if (err)
                return -errno;

	if ((cmd == MTKETH_MII_WRITE) || (cmd == MTKETH_MII_WRITE_CL45) ||
	    (cmd == SIOCSMIIREG))
		*val = (is_priv) ? mtk_mii.val_in : mii.val_in;
	else
		*val = (is_priv) ? mtk_mii.val_out : mii.val_out;

        return 0;
}

int read_wan_lan_id()
{
	unsigned int port_lan=5, port_wan=6;
	unsigned int dev = 0;	

	lan_phy_id = mdio_phy_id_c45(port_lan, dev);
	wan_phy_id = mdio_phy_id_c45(port_wan, dev);	
}

//mii_mgr_cl45 -g -p 5 -r 1
int read_status_wan_lan()
{	
	unsigned int val = 0;	

	__phy_op("eth0", lan_phy_id, 1, &val, MTKETH_MII_READ_CL45, 1);
	if(val == 0x796d && last_lan_status == 0)
	{
		MAKE_BRIGHTNESS(lan_fd);
		last_lan_status = 1;
	}		
	else if(val != 0x796d && last_lan_status == 1)
	{
		MAKE_NOBRIGHTNESS(lan_fd);
		last_lan_status = 0;
	}
		
	__phy_op("eth0", wan_phy_id, 1, &val, MTKETH_MII_READ_CL45, 1);	
	if(val == 0x796d && last_wan_status == 0)
	{
		MAKE_BRIGHTNESS(wan_fd);
		last_wan_status = 1;
	}		
	else if(val != 0x796d && last_wan_status == 1)
	{
		MAKE_NOBRIGHTNESS(wan_fd);
		last_wan_status = 0;
	}

	return 0;
}

int main(int argc, char *argv[])
{
	MAKE_NOBRIGHTNESS(wan_fd);
	MAKE_NOBRIGHTNESS(lan_fd);
	__phy_op_init();
	wan_lan_fd_init();
	read_wan_lan_id();
	
	while(1){
		read_status_wan_lan();
		sleep(2);
	}

	close(wan_fd);
	close(lan_fd);
}